/*
 * @(#)PortMap.java	1.0 Mar 8, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.net;

import static org.eoti.net.PortConfiguration.Protocol;

import java.util.LinkedHashMap;
import java.util.concurrent.locks.ReentrantLock;

public class PortMap
{
	public enum WellKnownPort
	{
		echo(Protocol.tcp, 7),
		echo2(Protocol.udp, 7),
		discard(Protocol.tcp, 9),
		discard2(Protocol.udp, 9),
		systat(Protocol.tcp, 11),
		systat2(Protocol.udp, 11),
		daytime(Protocol.tcp, 13),
		daytime2(Protocol.udp, 13),
		qotd(Protocol.tcp, 17),
		qotd2(Protocol.udp, 17),
		chargen(Protocol.tcp, 19),
		chargen2(Protocol.udp, 19),
		ftpdata(Protocol.tcp, 20),
		ftp(Protocol.tcp, 21),
		telnet(Protocol.tcp, 23),
		smtp(Protocol.tcp, 25),
		time(Protocol.tcp, 37),
		time2(Protocol.udp, 37),
		rlp(Protocol.udp, 39),
		nameserver(Protocol.tcp, 42),
		nameserver2(Protocol.udp, 42),
		nicname(Protocol.tcp, 43),
		domain(Protocol.udp, 53),
		domain2(Protocol.tcp, 53),
		bootps(Protocol.udp, 67),
		bootpc(Protocol.udp, 68),
		tftp(Protocol.udp, 69),
		gopher(Protocol.tcp, 70),
		finger(Protocol.tcp, 79),
		http(Protocol.tcp, 80),
		kerberos(Protocol.tcp, 88),
		kerberos2(Protocol.udp, 88),
		hostname(Protocol.tcp, 101),
		isotsap(Protocol.tcp, 102),
		rtelnet(Protocol.tcp, 107),
		pop2(Protocol.tcp, 109),
		pop3(Protocol.tcp, 110),
		sunrpc(Protocol.tcp, 111),
		sunrpc2(Protocol.udp, 111),
		auth(Protocol.tcp, 113),
		uucppath(Protocol.tcp, 117),
		nntp(Protocol.tcp, 119),
		ntp(Protocol.udp, 123),
		epmap(Protocol.tcp, 135),
		epmap2(Protocol.udp, 135),

		ldap(Protocol.tcp, 389),
		https(Protocol.tcp, 443),
		https2(Protocol.tcp, 443),
		syslog(Protocol.udp, 514),
		http2(Protocol.tcp, 8080),
		;

/*
netbios-ns        137/tcp    nbname                 #NETBIOS Name Service
netbios-ns        137/udp    nbname                 #NETBIOS Name Service
netbios-dgm       138/udp    nbdatagram             #NETBIOS Datagram Service
netbios-ssn       139/tcp    nbsession              #NETBIOS Session Service
imap              143/tcp    imap4                  #Internet Message Access Protocol
pcmail-srv        158/tcp                           #PCMail Server
snmp              161/udp                           #SNMP
snmptrap          162/udp    snmp-trap              #SNMP trap
print-srv         170/tcp                           #Network PostScript
bgp               179/tcp                           #Border Gateway Protocol
irc               194/tcp                           #Internet Relay Chat Protocol
ipx               213/udp                           #IPX over IP
microsoft-ds      445/tcp
microsoft-ds      445/udp
kpasswd           464/tcp                           # Kerberos (v5)
kpasswd           464/udp                           # Kerberos (v5)
isakmp            500/udp    ike                    #Internet Key Exchange
exec              512/tcp                           #Remote Process Execution
biff              512/udp    comsat
login             513/tcp                           #Remote Login
who               513/udp    whod
cmd               514/tcp    shell
syslog            514/udp
printer           515/tcp    spooler
talk              517/udp
ntalk             518/udp
efs               520/tcp                           #Extended File Name Server
router            520/udp    route routed
timed             525/udp    timeserver
tempo             526/tcp    newdate
courier           530/tcp    rpc
conference        531/tcp    chat
netnews           532/tcp    readnews
netwall           533/udp                           #For emergency broadcasts
uucp              540/tcp    uucpd
klogin            543/tcp                           #Kerberos login
kshell            544/tcp    krcmd                  #Kerberos remote shell
new-rwho          550/udp    new-who
remotefs          556/tcp    rfs rfs_server
rmonitor          560/udp    rmonitord
monitor           561/udp
ldaps             636/tcp    sldap                  #LDAP over TLS/SSL
doom              666/tcp                           #Doom Id Software
doom              666/udp                           #Doom Id Software
kerberos-adm      749/tcp                           #Kerberos administration
kerberos-adm      749/udp                           #Kerberos administration
kerberos-iv       750/udp                           #Kerberos version IV
kpop             1109/tcp                           #Kerberos POP
phone            1167/udp                           #Conference calling
ms-sql-s         1433/tcp                           #Microsoft-SQL-Server
ms-sql-s         1433/udp                           #Microsoft-SQL-Server
ms-sql-m         1434/tcp                           #Microsoft-SQL-Monitor
ms-sql-m         1434/udp                           #Microsoft-SQL-Monitor
wins             1512/tcp                           #Microsoft Windows Internet Name Service
wins             1512/udp                           #Microsoft Windows Internet Name Service
ingreslock       1524/tcp    ingres
l2tp             1701/udp                           #Layer Two Tunneling Protocol
pptp             1723/tcp                           #Point-to-point tunnelling protocol
radius           1812/udp                           #RADIUS authentication protocol
radacct          1813/udp                           #RADIUS accounting protocol
nfsd             2049/udp    nfs                    #NFS server
knetd            2053/tcp                           #Kerberos de-multiplexor
man              9535/tcp                           #Remote Man Server
attunity-uda-server 2551/tcp # Attunity Connect
attunity-uda-server 2551/udp # Attunity Connect
 */

		WellKnownPort(PortConfiguration.Protocol proto, int port)
		{
			this.config = new PortConfiguration(proto,port);
		}
		protected PortConfiguration config;
		public PortConfiguration getConfig(){return config;}
	}

	protected LinkedHashMap<String,PortConfiguration> ports;
	protected PortMap()
	{
		ports = new LinkedHashMap<String,PortConfiguration>();
		for(WellKnownPort port : WellKnownPort.values())
			ports.put(port.toString(), port.getConfig());
	}

	private static ReentrantLock singletonLock = new ReentrantLock();
	private static PortMap singleton;

	public static PortMap getInstance(){
		// If singleton != null, then just return it (don't lock READ)
		if(singleton == null){
			// don't let more that one person create the singleton
			singletonLock.lock();

			// if we were waiting for a lock, then someone else already made it
			if(singleton == null)
				singleton = new PortMap();

			singletonLock.unlock();
		}

		return singleton;
	}

	public static void add(String name, PortConfiguration.Protocol proto, int port)
	{
		add(name, new PortConfiguration(proto, port));
	}

	public static void add(String name, PortConfiguration config)
	{
		getInstance().ports.put(name, config);
	}

	public static PortConfiguration get(String name)
	{
		return getInstance().ports.get(name);
	}
}
